using System;
using System.Globalization;

using Hangfire;
using Hangfire.Console;
using Hangfire.Dashboard.BasicAuthorization;
using Hangfire.Redis;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

using NP.BPMReportPlatform.EntityFrameworkCore;
using NP.Enterprise.Utils.Http;

using Serilog;
using Serilog.Events;

using Volo.Abp;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.Modularity;

namespace NP.BPMReportPlatform.BackgroundJobs.Host
{
    [DependsOn(
        typeof(BPMReportPlatformApplicationModule),
        typeof(BPMReportPlatformEntityFrameworkCoreModule),
        typeof(AbpAutofacModule),
        typeof(AbpCachingStackExchangeRedisModule),
        typeof(AbpEntityFrameworkCoreMySQLModule),
        // typeof(AbpAuditLoggingEntityFrameworkCoreModule),
        // typeof(AbpPermissionManagementEntityFrameworkCoreModule),
        // typeof(AbpSettingManagementEntityFrameworkCoreModule),
        typeof(AbpAspNetCoreSerilogModule)
    )]
    public class BpmReportPlatformBackgroundJobsHostModule : AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();

            string redisConn = configuration["Redis:Configuration"];

            ConfigureSerilog(context, configuration);
            ConfigureHealthChecks(context);

            ConfigureRedis(context, configuration, hostingEnvironment);

            //context.Services.PreConfigure<IGlobalConfiguration>(config =>
            //{
            //    //config.UseStorage(new SqlServerStorage(connstr));
            //    //config.UseRedisStorage(redisConn);
            //    config.UseConsole();
            //});

            context.Services.AddSingleton<INPRestHttpHelper, NPRestHttpHelper>();

            context.Services.AddSingleton(typeof(ILogger), Log.Logger);

            Configure<AbpBackgroundJobWorkerOptions>(options =>
            {
                options.DefaultTimeout = 864000; //10 days (as seconds)
            });

            CapConfigureServices(context.Services, configuration);
            ConfigureHangfire(context, configuration);
        }

        public override void OnPostApplicationInitialization(Volo.Abp.ApplicationInitializationContext context)
        {
            context.ServiceProvider
                .GetRequiredService<BpmReportPlatformJobCreator>()
                .CreateJobs(context.GetEnvironment());
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var configuration = context.GetConfiguration();
            var environment = context.GetEnvironment();

            app.UseHealthChecks("/health");

            var supportedCultures = new[]
            {
                new CultureInfo("zh-CN")
            };

            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("zh-CN"),
                // Formatting numbers, dates, etc.
                SupportedCultures = supportedCultures,
                // UI strings that we have localized.
                SupportedUICultures = supportedCultures
            });

            if (environment.EnvironmentName == "Local")
            {
                app.UseHangfireDashboard();
            }
            else
            {
                app.UseHangfireDashboard("/hangfire", new DashboardOptions
                {
                    Authorization = new[]
                    {
                        new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions
                        {
                            SslRedirect = false,          // 是否将所有非SSL请求重定向到SSL URL
                            RequireSsl = false,           // 需要SSL连接才能访问HangFire Dahsboard。强烈建议在使用基本身份验证时使用SSL
                            LoginCaseSensitive = false,   //登录检查是否区分大小写
                            Users = new[]                 //配置登陆账号和密码
                            {
                                new BasicAuthAuthorizationUser
                                {
                                    Login = configuration["Hangfire:Authorization:Login"],//用户名
                                    PasswordClear= configuration["Hangfire:Authorization:PasswordClear"]
                                }
                            }
                        })
                    }
                });
            }
        }

        private void ConfigureSerilog(ServiceConfigurationContext context, IConfiguration configuration)
        {
            // 使用serilog作为log发送方
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
                .Enrich.WithProperty("Application", "NP.BPMReportPlatform.BackgroundJobs.Host")
                .Enrich.FromLogContext()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();

            context.Services.AddLogging(loggingBuilder =>
                loggingBuilder.AddSerilog(dispose: true));
        }

        public void CapConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            services.AddCap(x =>
            {
                x.UseMySql(configuration["ConnectionStrings:BPM_Business"]);

                x.UseRabbitMQ(option =>
                {
                    option.VirtualHost = configuration["RabbitMQ:Connections:Default:VirtualHost"];     //虚拟通道
                    option.HostName = configuration["RabbitMQ:Connections:Default:HostName"];           //IP地址
                    option.UserName = configuration["RabbitMQ:Connections:Default:UserName"];           //账号
                    option.Password = configuration["RabbitMQ:Connections:Default:Password"];           //密码 
                    option.Port = Convert.ToInt32(configuration["RabbitMQ:Connections:Default:Port"]);  //端口号
                });

                x.FailedRetryCount = 2;
                x.FailedRetryInterval = 5 * 60;
                x.FailedThresholdCallback = (type) =>
                {
                    Log.Logger.Error($"Cap异常：{type.Message}");
                };
            });
        }


        private void ConfigureHealthChecks(ServiceConfigurationContext context)
        {
            context.Services.AddHealthChecks();
        }

        private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddHangfire(config =>
            {

                config.UseRedisStorage(configuration["Hangfire:RedisConfiguration"], configuration.GetSection("Hangfire:RedisOptions").Get<RedisStorageOptions>());


                //GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 3, DelaysInSeconds = new int[] { 300 } });
            });

            context.Services.AddHangfireServer(options =>
            {
                options.Queues = new[]
                {
                    "default"
                };
            });
        }

        private void ConfigureRedis(
            ServiceConfigurationContext context,
            IConfiguration configuration,
            IWebHostEnvironment hostingEnvironment)
        {
            //configuration
            string redisConn = configuration["Redis:Configuration"];
            context.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = redisConn;
                options.InstanceName = "BpmReportBackJob";
            });
        }
    }
}